// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.statement.SQLSelect;
// import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
// import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr;
// import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.ArrayList;
// import java.util.List;

#include "ModelClause.h"
#include "../../visitor/OracleASTVisitor.h"
#include "../../../../visitor/SQLASTVisitor.h"
#include "../../../../ast/statement/SQLSelect.h"
#include "../../../../ast/SQLObject.h"
#include "../../../../../utils/listTran.h"
#include "../../../../../utils/ifeq.h"
#include "../../../../../utils/listAddAll.h"
#include "../../../../../Exception/UnsupportedOperationException.h"

ModelClause_CellReferenceOption_ptr ModelClause_CellReferenceOption::IgnoreNav = ModelClause_CellReferenceOption_ptr(new ModelClause_CellReferenceOption(1ULL << 0, make_string_ptr("IGNORE NAV")));
ModelClause_CellReferenceOption_ptr ModelClause_CellReferenceOption::KeepNav = ModelClause_CellReferenceOption_ptr(new ModelClause_CellReferenceOption(1ULL << 0, make_string_ptr("KEEP NAV")));
ModelClause_CellReferenceOption_ptr ModelClause_CellReferenceOption::UniqueDimension = ModelClause_CellReferenceOption_ptr(new ModelClause_CellReferenceOption(1ULL << 0, make_string_ptr("UNIQUE DIMENSION")));
ModelClause_CellReferenceOption_ptr ModelClause_CellReferenceOption::UniqueSingleReference = ModelClause_CellReferenceOption_ptr(new ModelClause_CellReferenceOption(1ULL << 0, make_string_ptr("UNIQUE SINGLE REFERENCE")));

ModelClause_CellReferenceOption::ModelClause_CellReferenceOption()
    : ModelClause_CellReferenceOption(0, nullptr)
{
}

ModelClause_CellReferenceOption::ModelClause_CellReferenceOption(uint64_t mask, string_ptr name)
{
  this->mask = mask;
  this->name = name;
}

string_ptr ModelClause_CellReferenceOption::toString()
{
  return name;
}

BOOL_ptr ModelClause_ReturnRowsClause::isAll()
{
  return all;
}

void ModelClause_ReturnRowsClause::setAll(BOOL_ptr all)
{
  this->all = all;
}

// @Override
void ModelClause_ReturnRowsClause::accept0(OracleASTVisitor_ptr visitor)
{
  visitor->visit(SharedObject(ModelClause_ReturnRowsClause));
  visitor->endVisit(SharedObject(ModelClause_ReturnRowsClause));
}

ModelClause_ReferenceModelClause::ModelClause_ReferenceModelClause()
{
  cellReferenceOptions = std::make_shared<std::list<ModelClause_CellReferenceOption_ptr>>();
}
ModelClause_CellReferenceOption_list_ptr ModelClause_ReferenceModelClause::getCellReferenceOptions()
{
  return cellReferenceOptions;
}

SQLExpr_ptr ModelClause_ReferenceModelClause::getName()
{
  return name;
}

void ModelClause_ReferenceModelClause::setName(SQLExpr_ptr name)
{
  this->name = name;
}

SQLSelect_ptr ModelClause_ReferenceModelClause::getSubQuery()
{
  return subQuery;
}

void ModelClause_ReferenceModelClause::setSubQuery(SQLSelect_ptr subQuery)
{
  this->subQuery = subQuery;
}

// @Override
void ModelClause_ReferenceModelClause::accept0(OracleASTVisitor_ptr visitor)
{
}

ModelClause_ModelColumnClause::ModelClause_ModelColumnClause()
{
  dimensionByColumns = std::make_shared<std::list<ModelClause_ModelColumn_ptr>>();
  measuresColumns = std::make_shared<std::list<ModelClause_ModelColumn_ptr>>();
}
ModelClause_ModelColumn_list_ptr ModelClause_ModelColumnClause::getDimensionByColumns()
{
  return dimensionByColumns;
}

ModelClause_ModelColumn_list_ptr ModelClause_ModelColumnClause::getMeasuresColumns()
{
  return measuresColumns;
}

ModelClause_QueryPartitionClause_ptr ModelClause_ModelColumnClause::getQueryPartitionClause()
{
  return queryPartitionClause;
}

void ModelClause_ModelColumnClause::setQueryPartitionClause(ModelClause_QueryPartitionClause_ptr queryPartitionClause)
{
  this->queryPartitionClause = queryPartitionClause;
}

string_ptr ModelClause_ModelColumnClause::getAlias()
{
  return alias;
}

void ModelClause_ModelColumnClause::setAlias(string_ptr alias)
{
  this->alias = alias;
}

// @Override
void ModelClause_ModelColumnClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_ModelColumnClause)))
  {
    acceptChild(visitor, queryPartitionClause);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<ModelClause_ModelColumn, SQLObject>(dimensionByColumns);
    acceptChild(visitor, tmp1);
    SQLObject_list_ptr tmp2 = ListTran::tran_class<ModelClause_ModelColumn, SQLObject>(measuresColumns);
    acceptChild(visitor, tmp2);
  }
  visitor->endVisit(SharedObject(ModelClause_ModelColumnClause));
}

SQLExpr_ptr ModelClause_ModelColumn::getExpr()
{
  return expr;
}

void ModelClause_ModelColumn::setExpr(SQLExpr_ptr expr)
{
  this->expr = expr;
}

string_ptr ModelClause_ModelColumn::getAlias()
{
  return alias;
}

void ModelClause_ModelColumn::setAlias(string_ptr alias)
{
  this->alias = alias;
}

// @Override
void ModelClause_ModelColumn::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_ModelColumn)))
  {
    acceptChild(visitor, expr);
  }
  visitor->endVisit(SharedObject(ModelClause_ModelColumn));
}

ModelClause_QueryPartitionClause::ModelClause_QueryPartitionClause()
{
  exprList = std::make_shared<std::list<SQLExpr_ptr>>();
}
SQLExpr_list_ptr ModelClause_QueryPartitionClause::getExprList()
{
  return exprList;
}

void ModelClause_QueryPartitionClause::setExprList(SQLExpr_list_ptr exprList)
{
  this->exprList = exprList;
}

// @Override
void ModelClause_QueryPartitionClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_QueryPartitionClause)))
  {
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLExpr, SQLObject>(exprList);
    acceptChild(visitor, tmp1);
  }
}

ModelClause_MainModelClause::ModelClause_MainModelClause()
{
  cellReferenceOptions = std::make_shared<std::list<ModelClause_CellReferenceOption_ptr>>();
}
ModelClause_ModelRulesClause_ptr ModelClause_MainModelClause::getModelRulesClause()
{
  return modelRulesClause;
}

void ModelClause_MainModelClause::setModelRulesClause(ModelClause_ModelRulesClause_ptr modelRulesClause)
{
  this->modelRulesClause = modelRulesClause;
}

ModelClause_CellReferenceOption_list_ptr ModelClause_MainModelClause::getCellReferenceOptions()
{
  return cellReferenceOptions;
}

ModelClause_ModelColumnClause_ptr ModelClause_MainModelClause::getModelColumnClause()
{
  return modelColumnClause;
}

void ModelClause_MainModelClause::setModelColumnClause(ModelClause_ModelColumnClause_ptr modelColumnClause)
{
  this->modelColumnClause = modelColumnClause;
}

SQLExpr_ptr ModelClause_MainModelClause::getMainModelName()
{
  return mainModelName;
}

void ModelClause_MainModelClause::setMainModelName(SQLExpr_ptr mainModelName)
{
  this->mainModelName = mainModelName;
}

// @Override
void ModelClause_MainModelClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_MainModelClause)))
  {
    acceptChild(visitor, mainModelName);
    acceptChild(visitor, modelColumnClause);
    acceptChild(visitor, modelRulesClause);
  }
  visitor->endVisit(SharedObject(ModelClause_MainModelClause));
}

ModelClause_ModelRulesClause::ModelClause_ModelRulesClause()
{
  options = std::make_shared<std::list<ModelClause_ModelRuleOption_ptr>>();
  cellAssignmentItems = std::make_shared<std::list<ModelClause_CellAssignmentItem_ptr>>();
}
SQLExpr_ptr ModelClause_ModelRulesClause::getUntil()
{
  return until;
}

void ModelClause_ModelRulesClause::setUntil(SQLExpr_ptr until)
{
  this->until = until;
}

SQLExpr_ptr ModelClause_ModelRulesClause::getIterate()
{
  return iterate;
}

void ModelClause_ModelRulesClause::setIterate(SQLExpr_ptr iterate)
{
  this->iterate = iterate;
}

ModelClause_ModelRuleOption_list_ptr ModelClause_ModelRulesClause::getOptions()
{
  return options;
}

ModelClause_CellAssignmentItem_list_ptr ModelClause_ModelRulesClause::getCellAssignmentItems()
{
  return cellAssignmentItems;
}

// @Override
void ModelClause_ModelRulesClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_ModelRulesClause)))
  {
    acceptChild(visitor, iterate);
    acceptChild(visitor, until);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<ModelClause_CellAssignmentItem, SQLObject>(cellAssignmentItems);
    acceptChild(visitor, tmp1);
  }
  visitor->endVisit(SharedObject(ModelClause_ModelRulesClause));
}

ModelClause_ModelRuleOption_ptr ModelClause_ModelRuleOption::UPSERT = ModelClause_ModelRuleOption_ptr(new ModelClause_ModelRuleOption(1ULL << 0, make_string_ptr("UPSERT")));
ModelClause_ModelRuleOption_ptr ModelClause_ModelRuleOption::UPDATE = ModelClause_ModelRuleOption_ptr(new ModelClause_ModelRuleOption(1ULL << 1, make_string_ptr("UPDATE")));
ModelClause_ModelRuleOption_ptr ModelClause_ModelRuleOption::AUTOMATIC_ORDER = ModelClause_ModelRuleOption_ptr(new ModelClause_ModelRuleOption(1ULL << 2, make_string_ptr("AUTOMATIC ORDER")));
ModelClause_ModelRuleOption_ptr ModelClause_ModelRuleOption::SEQUENTIAL_ORDER = ModelClause_ModelRuleOption_ptr(new ModelClause_ModelRuleOption(1ULL << 3, make_string_ptr("SEQUENTIAL ORDER")));

ModelClause_ModelRuleOption::ModelClause_ModelRuleOption(uint64_t mask, string_ptr name)
{
  this->name = name;
  this->mask = mask;
}

string_ptr ModelClause_ModelRuleOption::toString()
{
  return name;
}

ModelClause_ModelRuleOption_ptr ModelClause_CellAssignmentItem::getOption()
{
  return option;
}

void ModelClause_CellAssignmentItem::setOption(ModelClause_ModelRuleOption_ptr option)
{
  this->option = option;
}

ModelClause_CellAssignment_ptr ModelClause_CellAssignmentItem::getCellAssignment()
{
  return cellAssignment;
}

void ModelClause_CellAssignmentItem::setCellAssignment(ModelClause_CellAssignment_ptr cellAssignment)
{
  this->cellAssignment = cellAssignment;
}

SQLOrderBy_ptr ModelClause_CellAssignmentItem::getOrderBy()
{
  return orderBy;
}

void ModelClause_CellAssignmentItem::setOrderBy(SQLOrderBy_ptr orderBy)
{
  this->orderBy = orderBy;
}

SQLExpr_ptr ModelClause_CellAssignmentItem::getExpr()
{
  return expr;
}

void ModelClause_CellAssignmentItem::setExpr(SQLExpr_ptr expr)
{
  this->expr = expr;
}

// @Override
void ModelClause_CellAssignmentItem::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_CellAssignmentItem)))
  {
    acceptChild(visitor, cellAssignment);
    acceptChild(visitor, orderBy);
    acceptChild(visitor, expr);
  }
  visitor->endVisit(SharedObject(ModelClause_CellAssignmentItem));
}

ModelClause_CellAssignment::ModelClause_CellAssignment()
{
  conditions = std::make_shared<std::list<SQLExpr_ptr>>();
}
SQLExpr_list_ptr ModelClause_CellAssignment::getConditions()
{
  return conditions;
}

SQLExpr_ptr ModelClause_CellAssignment::getMeasureColumn()
{
  return measureColumn;
}

void ModelClause_CellAssignment::setMeasureColumn(SQLExpr_ptr e)
{
  if (e != nullptr)
  {
    e->setParent(SharedObject(ModelClause_CellAssignment));
  }
  this->measureColumn = e;
}

// @Override
BOOL_ptr ModelClause_CellAssignment::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (this->measureColumn == expr)
  {
    setMeasureColumn(target);
    return BOOL::TRUE;
  }

  auto it_conditions = conditions->begin();
  for (int i = 0; i < conditions->size(); i++)
  {
    std::advance(it_conditions, i);
    if (*it_conditions == expr)
    {
      target->setParent(SharedObject(ModelClause_CellAssignment));
      *it_conditions = target;
      return BOOL::TRUE;
    }
  }

  return BOOL::FALSE;
}

// @Override
void ModelClause_CellAssignment::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause_CellAssignment)))
  {
    acceptChild(visitor, measureColumn);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLExpr, SQLObject>(conditions);
    acceptChild(visitor, tmp1);
  }
  visitor->endVisit(SharedObject(ModelClause_CellAssignment));
}

// @Override
bool ModelClause_CellAssignment::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (o == nullptr || getClass()->c_str() != o->getClass()->c_str())
  {
    return false;
  }

  ModelClause_CellAssignment_ptr that = std::dynamic_pointer_cast<ModelClause_CellAssignment>(o);

  if (measureColumn != nullptr ? !measureColumn->equals(that->measureColumn) : that->measureColumn != nullptr)
  {
    return false;
  }
  return IFEQ::ifeq<SQLExpr_ptr>(conditions, that->conditions);
}

// @Override
int ModelClause_CellAssignment::hashCode()
{
  int result = measureColumn != nullptr ? measureColumn->hashCode() : 0;
  result = 31 * result + typeid(*conditions).hash_code(); // conditions->hashCode();
  return result;
}

// @Override
void ModelClause_CellAssignment::accept0(SQLASTVisitor_ptr visitor)
{
  accept0(std::dynamic_pointer_cast<OracleASTVisitor>(visitor));
}

// @Override
SQLObject_ptr ModelClause_CellAssignment::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<ModelClause_CellAssignment>(new ModelClause_CellAssignment());
  std::shared_ptr<ModelClause_CellAssignment> x = std::dynamic_pointer_cast<ModelClause_CellAssignment>(clone_tmp);
  // ModelClause_CellAssignment x = new ModelClause_CellAssignment();
  if (measureColumn != nullptr)
  {
    x->setMeasureColumn(std::dynamic_pointer_cast<SQLExpr>(measureColumn->clone()));
  }
  return nullptr;
}

// @Override
SQLObject_list_ptr ModelClause_CellAssignment::getChildren()
{
  SQLObject_list_ptr children = std::make_shared<std::list<SQLObject_ptr>>();
  children->push_back(measureColumn);
  // children.addAll(conditions);
  Utils::ListAddAll<SQLExpr, SQLObject>(conditions, children);
  return children;
}

ModelClause::ModelClause()
{
  cellReferenceOptions = std::make_shared<std::list<ModelClause_CellReferenceOption_ptr>>();
  referenceModelClauses = std::make_shared<std::list<ModelClause_ReferenceModelClause_ptr>>();
}
// @Override
void ModelClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(ModelClause)))
  {
    acceptChild(visitor, returnRowsClause);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<ModelClause_ReferenceModelClause, SQLObject>(referenceModelClauses);
    acceptChild(visitor, tmp1);
    acceptChild(visitor, mainModel);
  }
  visitor->endVisit(SharedObject(ModelClause));
}

ModelClause_MainModelClause_ptr ModelClause::getMainModel()
{
  return mainModel;
}

void ModelClause::setMainModel(ModelClause_MainModelClause_ptr mainModel)
{
  this->mainModel = mainModel;
}

ModelClause_ReturnRowsClause_ptr ModelClause::getReturnRowsClause()
{
  return returnRowsClause;
}

void ModelClause::setReturnRowsClause(ModelClause_ReturnRowsClause_ptr returnRowsClause)
{
  this->returnRowsClause = returnRowsClause;
}

ModelClause_ReferenceModelClause_list_ptr ModelClause::getReferenceModelClauses()
{
  return referenceModelClauses;
}

ModelClause_CellReferenceOption_list_ptr ModelClause::getCellReferenceOptions()
{
  return cellReferenceOptions;
}

SQLObject_ptr ModelClause::clone()
{
  throw new UnsupportedOperationException();
}
